[% setvar title Arrays: Use list reference for multidimensional array access %]
<div id="archive-notice">
    <h3>This file is part of the Perl 6 Archive</h3>
    <p>To see what is currently happening visit <a href="http://www.perl6.org/">http://www.perl6.org/</a></p>
</div>
<div class='pod'>
<a name='TITLE'></a><h1>TITLE</h1>
<p>Arrays: Use list reference for multidimensional array access</p>
<a name='VERSION'></a><h1>VERSION</h1>
<pre>   Maintainer: Buddha Buck &lt;<a href='mailto:bmbuck@14850.com'>bmbuck@14850.com</a>&gt;
   Date: 8 Sep 2000
   Last Modified: 19 Sep 2000
   Mailing List: <a href='mailto:perl6-language-data@perl.org'>perl6-language-data@perl.org</a>
   Number: 204
   Version: 2
   Status: Frozen</pre>
<a name='ABSTRACT'></a><h1>ABSTRACT</h1>
<p>This RFC proposes that array indexing syntax be extended to use references
to integer lists as indices for multidimensional arrays.</p>
<a name='SUMMARY OF DISCUSSION'></a><h1>SUMMARY OF DISCUSSION</h1>
<p>Most of the discussion concerning this RFC accepted it as-is as a workable
syntax.  It meets most of the requirements for multidimensional array access
that have been discussed.</p>
<p>Ilya Zakharevich brought up the issue of a potential problem with
objects which use blessed list references as their internal structure,
and their use as indices.  Given a Bignum class, which stores its
(external) value internally as a list of integers, doing something
like:</p>
<p>my $bignum = Bignum-&gt;new(23) # stored internally as [ 2, 3 ]
print $array[$bignum]; # should it print $array[23] or $array[[2,3]]?</p>
<p>can be ambiguous.  I'm not so sure.  I think that $bignum is not
legal, under Perl5, to be an array index, and that if it is going to
be use so, it would need to be $array[$bugnum-&gt;value] anyway.</p>
<a name='DESCRIPTION'></a><h1>DESCRIPTION</h1>
<p>Currently in Perl5, arrays can be indexed by a single integer, or sliced
by a list of integers. This notation is sufficient and convenient for one
dimensional arrays (like Perl5 has), but is problematic for
multidimensional arrays.</p>
<p>Because n-dimensional arrays have more than one dimension, their indices
are not simple integers, but rather n-tuples of integers. While lists are
natural Perl representations of n-tuples, they present problems when used
as multidimensional array indices:</p>
<ul>
<li><a name='It is ambiguous if @a[@point1,@point2] is a 2-element slice of a multidimensional array, or if it is a multi-element slice of a single dimensional array.'></a>It is ambiguous if @a[@point1,@point2] is a 2-element slice of a
multidimensional array, or if it is a multi-element slice of a single
dimensional array.</li>
<li><a name='Although $a[@point] is not as ambiguous (it is currently a syntax error), it still could be confusing, especially when seeing both $a[1,3,4] and @b[1,2,4].'></a>Although $a[@point] is not as ambiguous (it is currently a syntax error),
it still could be confusing, especially when seeing both $a[1,3,4] and
@b[1,2,4].</li>
<li><a name='It is inconvenient use a list of n-dimensional indices for a slice. By Perl syntax, such a list would have to be a list of lists, whereas currently Perl only allows lists of scalers.'></a>It is inconvenient use a list of n-dimensional indices for a slice. By
Perl syntax, such a list would have to be a list of lists, whereas
currently Perl only allows lists of scalers.</li>
</ul>
<p>A solution to these problems is to encapsulate a list of integers into a
scaler, such as using a list reference. By using list references for
indices (and lists of list references for slices), the multidimensional
case is similar to the unidimensional case: $a[$scaler] would access a
single element, @a[@list] would access a slice.</p>
<p>This would solve the problems above:</p>
<ul>
<li><a name='@a[$point1,$point2] is no longer ambiguous, but obviously a 2-element slice from the array @a. The dimensionality of @a is not an issue with this syntax.'></a>@a[$point1,$point2] is no longer ambiguous, but obviously a 2-element
slice from the array @a. The dimensionality of @a is not an issue with
this syntax.</li>
<li><a name='Multidimensional and unidimensional array access both use $a[$point], so $a[1,3,4] will not be seen. Instead, any confusion would have to be between $a[[1,3,4]] and @b[1,2,4]. Since $a[[1,3,4]] is an array indexed by a single scaler value (the listref [1,3,4]), whereas @b[1,2,4] is an array indexed by a list of scaler values explains clearly (and possibly redundantly) the use of $ and @ as prefixes.'></a>Multidimensional and unidimensional array access both use $a[$point], so
$a[1,3,4] will not be seen. Instead, any confusion would have to be
between $a[[1,3,4]] and @b[1,2,4]. Since $a[[1,3,4]] is an array indexed
by a single scaler value (the listref [1,3,4]), whereas @b[1,2,4] is an
array indexed by a list of scaler values explains clearly (and possibly
redundantly) the use of $ and @ as prefixes.</li>
<li><a name='List of lists are naturally stored as list of scalar references to lists. As such, the natural representation of lists of lists ties in well with taking multidimensional array slices:'></a>List of lists are naturally stored as list of scalar references to lists.
As such, the natural representation of lists of lists ties in well with
taking multidimensional array slices:</li>
<p>for my $t (1..10) { push @points,[getx($t),gety($t),getz($t)]; } $point =
$points[3];</p>
<p>@array[@points] = 1 x @points; $array[$point] = 0;</p>
</ul>
<p>This proposed syntax extends to unidimensional arrays as well. $a[[$b]]
being an alternative way of saying $a[$b], when $b is an integer. $a[[]]
would return the (unique) value of the zero-dimensional array @a, not the
value of the scaler $a.</p>
<p>A listref used as an index must have the same or lower cardinality as the
dimensionality of the array (if the array is declared with ':bounds'-- see
RFC 203), and must have elements within the declared or implied bounds of
the array indexed.</p>
<p>my int @array :bounds(3,3,3); $array[[0,1,2]] = 5; # OK, within bounds.
$array[[0,1,4]] = 5; # error, out of bounds $array[[1,2,1,2]] = 5; #
error, out of bounds, too many dimensions</p>
<p>If the cardinality (c) of the index is lower than the dimensions (d) of
the array, then the innermost (n-d) dimensions of the array are returned:</p>
<p>my int @array :bounds(3,3,3); $array[[1,2]] = (1,2,3,4); # Sets the line
at (1,2) to (1,2,3,4)</p>
<p>When a listref is used to index a list of lists, the returned list
reference is automatically dereferenced:</p>
<p>my @array( [0,1],
[1,2]);
my @a = @array[[0]]; # Returns (0,1), _not_ [0,1]</p>
<p>The ; operator (defined in RFC 205) is designed to return lists of
list refs, to make for efficient indexing and slicing of
multidimensional arrays.</p>
<p>@points = ((1,2);(3,4);5); @points = ([1,3,5],[1,4,5],[2,3,5],[2,4,5])
@array[@points]= 5 x @points;</p>
<a name='IMPLEMENTATION'></a><h1>IMPLEMENTATION</h1>
<p>Implementation of this feature is dependent on the underlying
implementation of multidimensional arrays. Other than that, it is a
straightforward enhancement of the semantics of list indexing.</p>
<a name='REFERENCES'></a><h1>REFERENCES</h1>
<p>RFC 202: Overview of multidimensional array RFCs</p>
<p>RFC 203: Notation for declaring and creating arrays</p>
<p>RFC 205: New operator ';' for creating array slices.</p>
<a name='ACKNOWLEDGEMENTS'></a><h1>ACKNOWLEDGEMENTS</h1>
<p>Jeremy Howard: Suggested listref indexing</p>
</div>
